<?php

namespace Payment\Common\LTFpay;

use Payment\Common\BaseData;
use Payment\Common\BaseStrategy;
use Payment\Common\LTFConfig;
use Payment\Common\PayException;
use Payment\Utils\ArrayUtil;
use Payment\Utils\Curl;

abstract class LTFBaseStrategy implements BaseStrategy{



	protected $config;

	/**
	 * 支付数据
	 * @var BaseData $reqData
	 */
	protected $reqData;

	/**
	 * FuBaseStrategy constructor.
	 * @param array $config
	 * @throws PayException
	 */
	public function __construct(array $config)
	{
		/* 设置内部字符编码为 UTF-8 */
		mb_internal_encoding("UTF-8");

		try {
			$this->config = new LTFConfig($config);
		} catch (PayException $e) {
			throw $e;
		}
	}

	/**
	 * 发送完了请求
	 * @param $body
	 * @return mixed
	 * @throws \Payment\Common\PayException
	 */
	protected function sendReq($body){
		$url = $this->getReqUrl();
		if (is_null($url)) {
			throw new PayException('目前不支持该接口。请联系开发者添加');
		}

		$responseTxt = $this->curlPost($body, $url);
		if ($responseTxt['error']) {
			throw new PayException('网络发生错误，请稍后再试curl返回码：' . $responseTxt['message']);
		}
		// 格式化为数组
		$retData = (json_decode($responseTxt['body'],true));

		if ($retData['code'] != 'SUCCESS') {
			throw new PayException('支付平台返回错误提示:' . $retData['subMsg']);
		}

		return $retData;
	}

	protected function curlPost($body, $url)
	{
		$curl = new Curl();
		return $curl->set([
			'CURLOPT_HEADER' => 0
		])->post($body, $url)->submit($url);
	}

	/**
	 * 处理具体的业务
	 *
	 * @param array $data
	 * @return mixed
	 * @throws \Payment\Common\PayException
	 */
	public function handle(array $data){
		// TODO: Implement handle() method.
		$buildClass = $this->getBuildDataClass();

		try {
			$this->reqData = new $buildClass($this->config, $data);
		} catch (PayException $e) {
			throw $e;
		}

		$this->reqData->setSign();

		$body = $this->reqData->getData();
		$ret = $this->sendReq($body);

		// 检查返回的数据是否被篡改
		$flag = true;// $this->verifySign($ret);
		if (!$flag) {
			throw new PayException('返回数据被篡改。请检查网络是否安全！');
		}

		return $this->retData($ret);
	}

	/**
	 * 获取请求地址
	 * @param null $url
	 * @return string
	 */
	protected function getReqUrl($url = null)
	{
		if(isset($this->config->base_url) && !empty($this->config->base_url)){
			$_pre = $this->config->base_url;
		}else{
			$_pre = LTFConfig::BASE_URL;
		}

		return $_pre.($url??LTFConfig::SCANPAY_URL);
	}

	/**
	 * 处理微信的返回值并返回给客户端
	 * @param array $ret
	 * @return mixed
	 *
	 */
	protected function retData(array $ret)
	{
		return $ret;
	}

	/**
	 * 检查微信返回的数据是否被篡改过
	 *
	 * @param array $retData
	 * @return boolean
	 * @throws \Exception
	 */
	protected function verifySign(array $retData)
	{
		$retSign = $retData['sign'];
		$values = ArrayUtil::removeKeys($retData, ['sign', 'sign_type']);

		$values = ArrayUtil::paraFilter($values);

		$values = ArrayUtil::arraySort($values);

		$signStr = ArrayUtil::createLinkstring($values);

		$signStr .= '&key=' . $this->config->md5Key;
		switch ($this->config->signType) {
			case 'MD5':
				$sign = md5($signStr);
				break;
			case 'HMAC-SHA256':
				$sign = hash_hmac('sha256', $signStr, $this->config->md5Key);
				break;
			default:
				$sign = '';
		}

		return strtoupper($sign) === $retSign;
	}

}
